#ifndef FKOBJECT3D_H
#define FKOBJECT3D_H

#include "FKDynamicObject.h"

#include "fkphisics_global.h"

//#include <QQuaternion>
#include <QVector3D>
#include <QVector4D>

class FKDisplayReferent;

class FKPHISICSSHARED_EXPORT FK_OBJECT(FKObject3D,FKDynamicObject)
    Q_OBJECT
    Q_PROPERTY(QList<qint32> cm READ getComponents WRITE C_components)
    Q_PROPERTY(QVector3D cpo READ getPosition WRITE C_position)
    Q_PROPERTY(QVector4D cr READ getRotation WRITE C_rotation)
    Q_PROPERTY(bool clm READ getLinearMoveing WRITE C_linearMoveing)
    Q_PROPERTY(QVector3D cls READ getLinearSpeed WRITE C_linearSpeed)
    Q_PROPERTY(bool clg READ getLinearAccelerating WRITE C_linearAccelerating)
    Q_PROPERTY(QVector3D cla READ getLinearAcceleration WRITE C_linearAcceleration)
    Q_PROPERTY(bool cri READ getRotating WRITE C_rotating)
    Q_PROPERTY(QVector4D crs READ getRotationSpeed WRITE C_rotationSpeed)
    Q_PROPERTY(bool crg READ getRotationAccelerating WRITE C_rotationAccelerating)
    Q_PROPERTY(QVector4D cra READ getRotationAcceleration WRITE C_rotationAcceleration)
    Q_PROPERTY(QVector4D cc READ getColor WRITE C_color)
public:
    void bindToArea(QObject* area);

    void setPosition(const QVector3D& position);
    void setSinglePosition(const QVector3D& position);
    void move(const QVector3D& offset);
    void moveSingle(const QVector3D& offset);
    QVector3D position()const;
    void setSingleRotation(const QVector4D& rotation);
    void rotateSingle(const QVector4D& way);
    QVector4D rotation()const;

    void setLinearMoveing(const bool& t);
    bool linearMoveing()const;
    void setLinearSpeed(const QVector3D& speed);
    QVector3D linearSpeed()const;

    void setLinearAccelerating(const bool& t);
    bool linearAccelerating()const;
    void setLinearAcceleration(const QVector3D& acceleration);
    QVector3D linearAcceleration()const;

    void setRotating(const bool& t);
    bool rotating()const;
    void setRotationSpeed(const QVector4D& rotation);
    QVector4D rotationSpeed()const;

    void setRotationAccelerating(const bool& t);
    bool rotationAccelerating()const;
    void setRotationAcceleration(const QVector4D& acceleration);
    QVector4D rotationAcceleration()const;

    void setColor(const QVector4D& color);
    void blendColor(const QVector4D& color);
    void setSingleColor(const QVector4D& color);
    void blendSingleColor(const QVector4D& color);
    QVector4D color()const;

    void setSize(const float& s){if(servant)servant->size=s;}
    float size()const{return servant ? servant->size : 0;}

    QVector3D getPosition()const{return servant ? servant->position : QVector3D();}
    QVector4D getRotation()const{return servant ? servant->rotation : QVector4D();}
    bool getLinearMoveing()const{return servant ? servant->move : false;}
    QVector3D getLinearSpeed()const{return servant ? servant->linearSpeed : QVector3D();}
    bool getLinearAccelerating()const{return servant ? servant->accelerateMoveing : false;}
    QVector3D getLinearAcceleration()const{return servant ? servant->linearAcceleration : QVector3D();}
    bool getRotating()const{return servant ? servant->rotate : false;}
    QVector4D getRotationSpeed()const{return servant ? servant->rotationSpeed: QVector4D();}
    bool getRotationAccelerating()const{return servant ? servant->accelerateRotation : false;}
    QVector4D getRotationAcceleration()const{return servant ? servant->rotationAcceleration : QVector4D();}
    QVector4D getColor()const{return servant ? servant->color : QVector4D();}
    void addComponent(FKObject3D* component);
protected:
    void setDisplayReferent(FKDisplayReferent* referent){_referent=referent;}
    FKDisplayReferent* displayReferent()const{return _referent;}
    QList<FKObject3D*> components()const{return customValues ? customValues->components : QList<FKObject3D*>();}
    void refreshReferent();
private slots:
    void recalculate(const qint32 &ms);
signals:
    void moved(QVector3D from, QVector3D to);
private:
    void autoMoveReal(const QVector3D& offset);
    void autoMoveVisual(const QVector3D& offset);
//  virtual void installReferent(){}

    FKDisplayReferent* _referent;

    QList<qint32> getComponents()const;

    void customInitialization();
    void customDeinitialization();

    void C_components(const QList<qint32>& newComponents);
    void C_position(const QVector3D& position);
    void C_rotation(const QVector4D& rotation);
    void C_linearMoveing(const bool& t);
    void C_linearSpeed(const QVector3D& speed);
    void C_linearAccelerating(const bool& t);
    void C_linearAcceleration(const QVector3D& acceleration);
    void C_rotating(const bool& t);
    void C_rotationSpeed(const QVector4D& speed);
    void C_rotationAccelerating(const bool& t);
    void C_rotationAcceleration(const QVector4D& acceleration);
    void C_color(const QVector4D& color);

    struct Servant{
        Servant():color(0,0,0,255),move(false),accelerateMoveing(false),rotate(false),accelerateRotation(false),size(0){}
        QList<FKObject3D*> components;
        QVector3D position;
        QVector4D rotation;
        QVector3D linearSpeed;
        QVector3D linearAcceleration;
        QVector4D rotationSpeed;
        QVector4D rotationAcceleration;
        QVector4D color;
        bool move;
        bool accelerateMoveing;
        bool rotate;
        bool accelerateRotation;
        float size;
    };
    struct CustomValues{
        CustomValues():color(0,0,0,255),move(false),accelerateMoveing(false),rotate(false),accelerateRotation(false){}
        QList<FKObject3D*> components;
        QVector3D position;
        QVector4D rotation;
        QVector3D linearSpeed;
        QVector3D linearAcceleration;
        QVector4D rotationSpeed;
        QVector4D rotationAcceleration;
        QVector4D color;
        bool move;
        bool accelerateMoveing;
        bool rotate;
        bool accelerateRotation;
    };
};

#endif // FKOBJECT3D_H
